package com.web3.management.service;

import com.web3.management.dto.PageResponse;
import com.web3.management.dto.request.ConfigRequest;
import com.web3.management.dto.response.ConfigDetailResponse;
import com.web3.management.dto.response.ConfigHistoryResponse;
import com.web3.management.dto.response.ConfigListResponse;
import com.web3.management.entity.Config;
import com.web3.management.entity.ConfigHistory;
import com.web3.management.exception.BusinessException;
import com.web3.management.repository.ConfigHistoryRepository;
import com.web3.management.repository.ConfigRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 全局配置服务类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ConfigService {

    private final ConfigRepository configRepository;
    private final ConfigHistoryRepository configHistoryRepository;
    private final OperationLogService operationLogService;

    public Config getById(Integer id) {
        return configRepository.findById(id)
                .orElseThrow(() -> new BusinessException("配置不存在"));
    }

    public Config getByName(String name) {
        return configRepository.findByName(name).orElse(null);
    }

    public Config getActiveConfig() {
        return configRepository.findFirstByIsActiveOrderByUpdatedAtDesc(1).orElse(null);
    }

    public Config getActiveGlobalConfig() {
        return getActiveConfig();
    }

    @Transactional
    public Config save(Config config) {
        return configRepository.save(config);
    }

    @Transactional
    public void activateConfig(Integer configId) {
        Config config = getById(configId);
        configRepository.activateConfigAndDeactivateOthers(configId);
        operationLogService.record("ACTIVATE_CONFIG", "CONFIG", configId,
                String.format("激活全局配置 %s", config.getName()));
        log.info("激活全局配置成功: configId={}", configId);
    }

    public PageResponse<ConfigListResponse> getConfigPage(Integer page, Integer size, String name) {
        PageRequest pageRequest = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "updatedAt"));
        Page<Config> configPage;
        if (StringUtils.hasText(name)) {
            configPage = configRepository.findByNameContainingIgnoreCase(name, pageRequest);
        } else {
            configPage = configRepository.findAll(pageRequest);
        }

        List<ConfigListResponse> list = configPage.getContent().stream()
                .map(this::convertToListResponse)
                .collect(Collectors.toList());
        return PageResponse.of(configPage.getTotalElements(), page, size, list);
    }

    public ConfigDetailResponse getConfigDetail(Integer id) {
        Config config = getById(id);
        return convertToDetailResponse(config);
    }

    @Transactional
    public ConfigDetailResponse createConfig(ConfigRequest request) {
        if (configRepository.existsByName(request.getName())) {
            throw new BusinessException("配置名称已存在");
        }

        Config config = new Config();
        config.setName(request.getName());
        config.setFilePath(request.getFilePath());
        config.setConfigContent(request.getConfigContent());
        config.setIsActive(0);

        Config saved = configRepository.save(config);
        recordConfigHistory(saved.getId(), request.getConfigContent(), request.getChangeSummary());
        operationLogService.record("CREATE_CONFIG", "CONFIG", saved.getId(),
                String.format("创建全局配置 %s", saved.getName()));
        return convertToDetailResponse(saved);
    }

    @Transactional
    public ConfigDetailResponse updateConfig(Integer id, ConfigRequest request) {
        Config config = getById(id);

        if (!config.getName().equals(request.getName()) &&
                configRepository.existsByNameAndIdNot(request.getName(), id)) {
            throw new BusinessException("配置名称已存在");
        }

        config.setName(request.getName());
        config.setFilePath(request.getFilePath());
        config.setConfigContent(request.getConfigContent());

        Config saved = configRepository.save(config);
        recordConfigHistory(saved.getId(), request.getConfigContent(), request.getChangeSummary());
        operationLogService.record("UPDATE_CONFIG", "CONFIG", saved.getId(),
                String.format("更新全局配置 %s", saved.getName()));
        return convertToDetailResponse(saved);
    }

    @Transactional
    public void deleteConfig(Integer id) {
        Config config = getById(id);
        configRepository.delete(config);
        operationLogService.record("DELETE_CONFIG", "CONFIG", id,
                String.format("删除全局配置 %s", config.getName()));
    }

    public PageResponse<ConfigHistoryResponse> getConfigHistory(Integer configId, Integer page, Integer size) {
        PageRequest pageRequest = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt"));
        Page<ConfigHistory> historyPage = configHistoryRepository.findByConfigIdOrderByCreatedAtDesc(configId, pageRequest);
        List<ConfigHistoryResponse> list = historyPage.getContent().stream()
                .map(this::convertToHistoryResponse)
                .collect(Collectors.toList());
        return PageResponse.of(historyPage.getTotalElements(), page, size, list);
    }

    private ConfigListResponse convertToListResponse(Config config) {
        ConfigListResponse response = new ConfigListResponse();
        response.setId(config.getId());
        response.setName(config.getName());
        response.setFilePath(config.getFilePath());
        response.setIsActive(config.getIsActive());
        response.setUpdatedAt(config.getUpdatedAt());
        return response;
    }

    private ConfigDetailResponse convertToDetailResponse(Config config) {
        ConfigDetailResponse response = new ConfigDetailResponse();
        response.setId(config.getId());
        response.setName(config.getName());
        response.setFilePath(config.getFilePath());
        response.setConfigContent(config.getConfigContent());
        response.setIsActive(config.getIsActive());
        response.setCreatedAt(config.getCreatedAt());
        response.setUpdatedAt(config.getUpdatedAt());
        return response;
    }

    private ConfigHistoryResponse convertToHistoryResponse(ConfigHistory history) {
        ConfigHistoryResponse response = new ConfigHistoryResponse();
        response.setId(history.getId());
        response.setConfigId(history.getConfigId());
        response.setContent(history.getContent());
        response.setChangeSummary(history.getChangeSummary());
        response.setCreatedAt(history.getCreatedAt());
        return response;
    }

    private void recordConfigHistory(Integer configId, String content, String changeSummary) {
        ConfigHistory history = new ConfigHistory();
        history.setConfigId(configId);
        history.setContent(content);
        history.setChangeSummary(StringUtils.hasText(changeSummary) ? changeSummary : "配置变更");
        configHistoryRepository.save(history);
    }
}
